package com.ken.common.event.core.rabbitmq.config;

import com.ken.common.core.utils.BeanRegisterUtils;
import com.ken.common.event.apply.delay.DelayTime;
import com.ken.common.event.apply.handle.EventHandler;
import com.ken.common.event.apply.handle.annotation.EventType;
import com.ken.common.event.core.rabbitmq.constact.RabbitMqConstact;
import com.ken.common.event.core.rabbitmq.core.RabbitMQProducerStandard;
import com.ken.common.event.core.rabbitmq.listener.ConsumerListener;
import com.ken.common.event.framework.producer.ProducerStandard;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@ComponentScan
public class RabbitMqConfig {

    /**
     * RabbitMq相关配置 - 默认使用
     */
    @Configuration
    @ConditionalOnClass(RabbitTemplate.class)
    public static class RabbitMqProviderConfiguration{

        @Autowired
        private BeanRegisterUtils beanRegisterUtils;

        /**
         * 创建延迟消息的交换机
         * @return
         */
        @Bean
        public TopicExchange getExchangeDelay(){
            return new TopicExchange(RabbitMqConstact.EVENT_EXCHANGE_DELAY, true, false);
        }

        /**
         * 配置一个Topic类型的交换机 - 默认名称为event_exchange
         * @return
         */
        @Bean
        public TopicExchange getExchange(){
            return new TopicExchange(RabbitMqConstact.EVENT_EXCHANGE, true, false);
        }


        @Bean
        public ProducerStandard getProducerStandard (){
            return new RabbitMQProducerStandard();
        }

        /**
         * 创建延迟队列
         */
        @Bean
        public Binding getQueueDelay(TopicExchange getExchangeDelay){
            //获得所有延迟时间列表
            DelayTime[] values = DelayTime.values();

            //循环延迟时间
            for (DelayTime delayTime : values) {
                //创建队列
                Map<String, Object> arguments = new HashMap<>();
                //设置队列的过期时间
                arguments.put("x-message-ttl", delayTime.unit.toMillis(delayTime.time));
                arguments.put("x-dead-letter-exchange", RabbitMqConstact.EVENT_EXCHANGE);
                Queue queue = new Queue(RabbitMqConstact.EVENT_QUEUE_DELAY_PRFIX + delayTime.getName(), true, false, false, arguments);
                //注册队列
                beanRegisterUtils.registerBean(queue.getName(), queue);

                //创建绑定对象
                Binding binding = BindingBuilder.bind(queue).to(getExchangeDelay).with("#." + delayTime.getName());
                //注册绑定对象
                beanRegisterUtils.registerBean("binding-" + binding.hashCode(), binding);
            }
            return null;
        }
    }

    /**
     * RabbitMq 消费端配置
     */
    @Configuration
    @ConditionalOnClass(RabbitTemplate.class)
    @ConditionalOnBean(EventHandler.class)
    public static class RabbitMqConsumerConfiguration{

        @Autowired
        private BeanRegisterUtils beanRegisterUtils;

        @Value("${spring.application.name}")
        private String appName;

        @Autowired
        private List<EventHandler> eventHandlers;

        /**
         * 消费端配置队列
         * @return
         */
        @Bean
        public Queue getQueue(){
            return new Queue(RabbitMqConstact.EVENT_QUEUE_PRFIX + appName, true, false, false);
        }

        /**
         * 消费端队列和事件交换机的绑定
         */
        @Bean
        public Binding getBinding(TopicExchange getExchange, Queue getQueue){
            //循环所有的事件处理器
            eventHandlers.forEach(eventHandler -> {
                //依次获得每个事件处理器的@EventType注解
                Class<? extends EventHandler> c = eventHandler.getClass();
                EventType eventType = c.getAnnotation(EventType.class);
                //获得注解中的事件类型 - 路由键
                String eventTypeInfo = eventType.value();

                //进行队列和交换机的绑定
                Binding binding = BindingBuilder.bind(getQueue).to(getExchange).with(eventTypeInfo + ".#");
                //手动进行Bean的注册 - 注册到Spring容器中
                beanRegisterUtils.registerBean("binding-" + binding.hashCode(), binding);
            });
            return null;
        }


        /**
         * 消费端监听器
         * @return
         */
        @Bean
        public ConsumerListener getConsumerListener(){
            return new ConsumerListener();
        }
    }
}
